package com.example.author.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.author.entity.Author;
import com.example.author.entity.Authorinformation;
import com.example.author.entity.dto.AuthorDto;
import com.example.author.mapper.AuthorMapper;
import com.example.author.mapper.AuthorinformationMapper;
import com.example.author.service.IAuthorService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.common.dtos.ResponseResult;
import com.example.utils.RegexUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.TimeUnit;

import static com.example.utils.RedisConstants.*;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 凡哥哥
 * @since 2023-11-20
 */
@Service
@Slf4j
public class AuthorServiceImpl extends ServiceImpl<AuthorMapper, Author> implements IAuthorService {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private AuthorMapper authorMapper;
    @Autowired
    private AuthorinformationMapper authorinformationMapper;
    /**
     * 用户登录
     *
     * @param phone,password
     * @return
     */
    @Override
    public ResponseResult<Author> login(String phone,String password) {

        //1.根据作者名查询数据库用户信息

        //条件构造器
        LambdaQueryWrapper<Author> lqw1 = new LambdaQueryWrapper();
        lqw1.and(q -> q.eq(Author::getPhone, phone).eq(Author::getPassword,password));
        Author author1 = getOne(lqw1);
        //2.判断作者是否存在
        if (author1 == null) {
            //3.不存在，则返回错误信息
            return ResponseResult.errorResult(501,"账号或密码错误");
        }
        //4.存在，随机生成token，作为登陆令牌
        String token = UUID.randomUUID().toString(true);
        //5.将Author对象转换为HashMap存储到Redis中
        AuthorDto authorDto = BeanUtil.copyProperties(author1, AuthorDto.class,"description");
        Authorinformation byAuthorAll = authorinformationMapper.findByAuthorId(authorDto.getId());
        authorDto.setTotalCount(byAuthorAll.getTotalCount());
        authorDto.setFollower(byAuthorAll.getFollower());
        Duration duration = Duration.between(author1.getCreateTime(), LocalDateTime.now());
        authorDto.setExistTime((int) duration.toDays());
        Map<String, Object> authorMap = BeanUtil.beanToMap(authorDto, new HashMap<>(),
                CopyOptions.create()
                        .setIgnoreNullValue(true)
                        .setFieldValueEditor((fieldName, fieldValue) -> fieldValue.toString()));
        log.info("authorMap:{}",authorMap);
        String key = LOGIN_USER_KEY + token;
        stringRedisTemplate.opsForHash().putAll(key,authorMap);
        //6.设置token有效期
        stringRedisTemplate.expire(key,LOGIN_USER_TTL, TimeUnit.MINUTES);
        //返回token
        return ResponseResult.okUserOrToken(200,token,authorDto);
    }

    /**
     * 用户注册
     *
     * @param author
     * @return
     */
    @Override
    public ResponseResult<String> register(Author author) {
        //校验手机号
        if(stringRedisTemplate.opsForSet().isMember(REGISTER_PHONE_KEY, author.getPhone())){
            return ResponseResult.errorResult(501,"手机号已注册");
        }
        //从Redis中取出验证码,校验作者输入的验证码是否一致
        Optional<String> codeOptional = Optional.ofNullable(stringRedisTemplate.opsForValue().get(LOGIN_CODE_KEY + author.getPhone()));
        String code = codeOptional.orElse("null");
        String code1 = author.getCode();
        if (!code.equals(code1)){
            //不一致,返回验证码错误
            return ResponseResult.errorResult(501,"验证码错误");
        }
        //一致,保存作者
        Author author1 = new Author();
        author1.setPhone(author.getPhone());
        author1.setPassword(author.getPassword());
        this.save(author1);
        //存储手机号到Redis,用于校验是否已注册过
        stringRedisTemplate.opsForSet().add(REGISTER_PHONE_KEY, author.getPhone());
        return ResponseResult.okResult("注册成功");
    }


    /**
     * 用户手机号
     *
     * @param phone
     * @return
     */
    @Override
    public ResponseResult<String> sendCode(String phone) {
        // TODO 发送短信验证码并保存验证码
        //1.校验手机号
        if (RegexUtils.isPhoneInvalid(phone)) {
            //2.如果不符合，返回错误信息
            return ResponseResult.errorResult(500,"手机号格式错误!");
        }
        //3.从缓存中校验手机号是否存在,存在就直接返回错误信息
        if(stringRedisTemplate.opsForSet().isMember(REGISTER_PHONE_KEY, phone)){
            return ResponseResult.errorResult(500,"手机号已注册");
        }
        //4.不存在,则手机号注册用户,生成验证码
        String code = RandomUtil.randomNumbers(6);
        //5.将验证码存入Redis中
        stringRedisTemplate.opsForValue().set(LOGIN_CODE_KEY + phone,code,LOGIN_CODE_TTL, TimeUnit.MINUTES);
        //6.给用户发送验证码
        return ResponseResult.okResult(code);
    }

}
